/******************************************************************************
 * @file     flash.c
 * @brief    Bootloader中flash外设相关函数
 * @author   Ruilist
 * @date     2025-08-15
 * @version  V1.0.0
 * @copyright Copyright (c) 2025
 *
 * @note     1 tab = 4 space
 *
 * @par 日志:
 * - V1.0.0 2025-08-15 Ruilist
 *****************************************************************************/

//******************************** Includes *********************************//

#include "flash.h"

//******************************** Includes *********************************//

//******************************** Defines **********************************//

const uint32_t Flash_Sectorsize[12] =
    {
        FLASH_Sector_0,   // Sector1
        FLASH_Sector_1,   // Sector2
        FLASH_Sector_2,   // Sector3
        FLASH_Sector_3,   // Sector4
        FLASH_Sector_4,   // Sector5
        FLASH_Sector_5,   // Sector6
        FLASH_Sector_6,   // Sector7
        FLASH_Sector_7,   // Sector8
        FLASH_Sector_8,   // Sector9
        FLASH_Sector_9,   // Sector10
        FLASH_Sector_10,  // Sector11
        FLASH_Sector_11   // Sector12
};

//******************************** Defines **********************************//

//******************************** Declaring ********************************//

/**
 * @brief   擦除flash
 *
 * @param   uint32_t addr 扇区地址
 * @param   uint32_t size 擦除大小
 *
 * @return  uint8_t
 * @retval  0 擦除成功
 * @retval  1 擦除失败
 *
 */
uint8_t Flash_erase( uint32_t addr, uint32_t size )
{
    // 判断size在几个扇区内

    uint32_t flash_start_sector = 0;
    uint32_t flash_end_sector   = 0;
    flash_start_sector          = STMFLASH_GetFlashSector( addr );
    flash_end_sector            = STMFLASH_GetFlashSector( addr + size );

    for ( uint8_t i = 0; i <= 12; i++ )
    {
        if ( ( Flash_Sectorsize[i] ) >= flash_start_sector && ( Flash_Sectorsize[i] ) <= flash_end_sector )
        {
            if ( EreaseAppSector( Flash_Sectorsize[i] ) != FLASH_COMPLETE )
                return 1;
        }
    }
    return 0;
}

/**
 * @brief   擦除flash
 *
 * @param   uint32_t addr 扇区地址
 *
 * @return  uint16_t
 * @retval  扇区地址
 *
 */
uint16_t STMFLASH_GetFlashSector( uint32_t addr )
{
    if ( addr < ADDR_FLASH_SECTOR_1 )
        return FLASH_Sector_0;
    else if ( addr < ADDR_FLASH_SECTOR_2 )
        return FLASH_Sector_1;
    else if ( addr < ADDR_FLASH_SECTOR_3 )
        return FLASH_Sector_2;
    else if ( addr < ADDR_FLASH_SECTOR_4 )
        return FLASH_Sector_3;
    else if ( addr < ADDR_FLASH_SECTOR_5 )
        return FLASH_Sector_4;
    else if ( addr < ADDR_FLASH_SECTOR_6 )
        return FLASH_Sector_5;
    else if ( addr < ADDR_FLASH_SECTOR_7 )
        return FLASH_Sector_6;
    else if ( addr < ADDR_FLASH_SECTOR_8 )
        return FLASH_Sector_7;
    else if ( addr < ADDR_FLASH_SECTOR_9 )
        return FLASH_Sector_8;
    else if ( addr < ADDR_FLASH_SECTOR_10 )
        return FLASH_Sector_9;
    else if ( addr < ADDR_FLASH_SECTOR_11 )
        return FLASH_Sector_10;
    return FLASH_Sector_11;
}

/**
 * @brief   flash扇区解锁
 *
 * @param   void
 *
 * @return  void
 *
 */
void Flash_Unlock( void )
{
    FLASH_Unlock();
    while ( FLASH_GetStatus() == FLASH_BUSY )
    {
    }
}

/**
 * @brief   flash扇区上锁
 *
 * @param   void
 *
 * @return  void
 *
 */
void Flash_Lock( void )
{
    FLASH_Lock();
}

/**
 * @brief   flash扇区擦除
 *
 * @param   uint32_t FLASH_Sector 扇区地址
 *
 * @return  FLASH_Status
 *
 */
FLASH_Status EreaseAppSector( uint32_t FLASH_Sector )
{
    Flash_Unlock();
    FLASH_Status FLASHStatus = FLASH_EraseSector( FLASH_Sector, VoltageRange_3 );
    Flash_Lock();
    return FLASHStatus;
}

/**
 * @brief   flash写入
 *
 * @param   uint32_t address 写入地址
 * @param   uint32_t data    写入数据
 *
 * @return  void
 *
 */
void Flash_Write( uint32_t address, uint32_t data )
{
    Flash_Unlock();
    FLASH_ProgramWord( address, data );
    Flash_Lock();
}

//******************************** Declaring ********************************//
